package jp.ac.jaist.control;

import jp.ac.jaist.computation.RMPIReliabilityCalculator;
import jp.ac.jaist.input.RMPIIAWrapper;
import jp.ac.jaist.input.RMPIInputModeler;
import jp.ac.jaist.message.RMPIIMException;
import jp.ac.jaist.simulation.RMPIReliabilitySimulationListener;
import jp.ac.jaist.simulation.RMPIReliabilitySimulator;
import org.apache.xmlbeans.XmlError;

import java.util.List;

public class RMPIController {
    /**
     * The private constructor.
     */
    private RMPIController() {

    }

    /**
     * Get a new instance.
     *
     * @return the newly created instance.
     */
    public static RMPIController newInstance() {
        return new RMPIController();
    }

    /**
     * Validate the input model from a file .
     *
     * @param inputModelFilename the filename of the input model.
     * @param outputContent      the output content.
     * @return the validated input model.
     */
    public RMPIInputModeler validateInputModelFromFile(String inputModelFilename, StringBuilder outputContent) {
        RMPIInputModeler oInputModeler = RMPIInputModeler.newInstance();
        try {
            oInputModeler.setInputModelFilename(inputModelFilename);

            outputContent.append("# The input model is valid.\n");
        } catch (RMPIIMException oEx) {
            outputContent.append(oEx.getMessage()).append("\n");

            List<XmlError> oXMLErrors = oInputModeler.getXMLErrors();

            if (oXMLErrors != null) {
                for (XmlError oXMLError : oXMLErrors) {
                    outputContent.append("Line ").append(oXMLError.getLine()).append(": ").append(oXMLError.getMessage()).append("\n");
                }
            }

        }

        return oInputModeler;
    }

    /**
     * Validate the input model from a string .
     *
     * @param inputModelAsString the input model as string.
     * @param outputContent      the output content.
     * @return the validated input model.
     */
    public RMPIInputModeler validateInputModelFromString(String inputModelAsString, StringBuilder outputContent) {
        RMPIInputModeler oInputModeler = RMPIInputModeler.newInstance();
        try {
            oInputModeler.setInputModel(inputModelAsString);

            outputContent.append("# The input model is valid.\n");
        } catch (RMPIIMException oEx) {
            outputContent.append(oEx.getMessage()).append("\n");

            List<XmlError> oXMLErrors = oInputModeler.getXMLErrors();

            if (oXMLErrors != null) {
                for (XmlError oXMLError : oXMLErrors) {
                    outputContent.append("Line ").append(oXMLError.getLine()).append(": ").append(oXMLError.getMessage()).append("\n");
                }
            }

        }

        return oInputModeler;
    }

    /**
     * Conduct a reliability prediction.
     *
     * @param inputModel the input model.
     * @return an equivalent internal activity with the reliability-related probabilities.
     */
    public RMPIIAWrapper conductReliabilityPrediction(RMPIInputModeler inputModel) {
        RMPIReliabilityCalculator oCalculator = RMPIReliabilityCalculator.newInstance(inputModel);
        return oCalculator.calculateReliabilityRelatedProbabilities();
    }

    /**
     * Conduct a reliability simulation.
     *
     * @param inputModel   the input model.
     * @param numberOfRuns the number of runs.
     * @param listeners    the array of listeners.
     * @return the reliability simulator for later usages.
     */
    public RMPIReliabilitySimulator conductReliabilitySimulation(RMPIInputModeler inputModel, int numberOfRuns, RMPIReliabilitySimulationListener[] listeners) {
        RMPIReliabilitySimulator oSimulator = RMPIReliabilitySimulator.newInstance(inputModel, numberOfRuns);
        for (RMPIReliabilitySimulationListener oListener : listeners) {
            oSimulator.addListener(oListener);
        }

        oSimulator.setPriority(Thread.MAX_PRIORITY);
        oSimulator.start();

        return oSimulator;
    }
}
